﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Text.RegularExpressions;
using System.Threading;
using System.IO;

namespace PIM_ATE
{
    class RCUrunner
    {
        MircoComHelper m_comObj;
        public string m_sComName;
        bool m_isConnected;
        const string lf = "\r\n";

        public string cmd = "";
        public string result = "";
         int result_f = 1;
        public string[] m_lstSerialNumber;

        
        public RCUrunner(string ComName)
        {
            m_comObj = new MircoComHelper();
                        m_isConnected = false;
            m_sComName = ComName;
        }

        ~RCUrunner()
        {
            if (m_isConnected)
            {
                m_comObj.Close();
            }
        }

        public void record_SN(string procodeSN)
        {
            string message = "";
            message += string.Format("天线追溯号：{0}\n", procodeSN) + "\r\n";
            message += DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff") + "\r\n";
            string sFilePath = System.Windows.Forms.Application.StartupPath + "\\LogMessage";
            if (!Directory.Exists(sFilePath))
            {
                Directory.CreateDirectory(sFilePath);
            }

            string sFileName = "ATE测试交互过程.txt";
            sFileName = sFilePath + "\\" + sFileName;             FileStream fs = new FileStream(sFileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
            StreamWriter sw = new StreamWriter(fs);
            sw.WriteLine(message);
            sw.Close();
            fs.Close();
        }

        public bool connect(string procodeSN)
        {
            if (!m_isConnected)
            {
                m_isConnected = m_comObj.Connect(m_sComName);

            }

            record_SN(procodeSN);
            return m_isConnected;
        }

        public void close()
        {
            if (m_isConnected)
            {
                m_comObj.Close();
                m_isConnected = false;
            }
        }

        #region cmd
        public string[] get_list(int list_count = 1)
        {
            result = "";
            cmd = "list\r\n";

            m_comObj.m_iCountEnding = list_count;
            if (m_comObj.StartWrite(Encoding.ASCII.GetBytes(cmd)))
            {
                result = Encoding.ASCII.GetString(m_comObj.StartRead());
                try
                {
                                                                                                                        string[] temp = result.Split('\n');
                    string[] lstSerialNumber = new string[temp.Length - 1];
                    for (int i = 0; i < lstSerialNumber.Length; i++)
                    {
                        lstSerialNumber[i] = temp[i].Split('=')[1].Trim();
                    }

                    record_message();
                    m_comObj.m_iCountEnding = 1;
                    return lstSerialNumber;
                }
                catch{ }
            }

            m_comObj.m_iCountEnding = 1;
            record_message();
            return null;
        }

        public bool set_debug_mode(string sn)
        {
            result = "";
            cmd = "debug " + sn + "\r\n";
            bool ret = m_comObj.StartWrite(Encoding.ASCII.GetBytes(cmd));
            if (ret)
            {
                result = Encoding.ASCII.GetString(m_comObj.StartRead());
                                                record_message();
                return result.ToLower().Contains("enabled");
            }

            record_message();
            return false;
        }

        public bool set_agl(string sn, int unit_index, int agl, int speed = 0)
        {
            result_f = 2;
            result = "";
            cmd = string.Format("setagl {0},{1},{2},{3}\r\n", sn, unit_index, speed, agl);
                                    m_comObj.StartWrite(Encoding.ASCII.GetBytes(cmd), true);
            if (m_comObj.StartRead("setting", 1000 * 120) != null)
            {
                Byte[] b = m_comObj.StartRead("$->:", 1000 * 120);
                if (b == null)
                {
                    result_f = 3;
                    record_message();
                    return false;
                }

                                                                                                                                                result = Encoding.ASCII.GetString(b);
                if(result.ToLower().Contains("angle setting failed"))
                {
                    record_message();
                    return false;
                }
                result_f = 1;
                record_message();
                return result.ToLower().Contains("succeed");
            }
            result_f = 3;
            record_message();
            return false;
        }

        public int get_agl(string sn, int unit_index)
        {
            result_f = 2;
            result = "";
            cmd = string.Format("getagl {0},{1}\r\n", sn, unit_index);
            bool ret = m_comObj.StartWrite(Encoding.ASCII.GetBytes(cmd), false, 1000);
            if (ret)
            {
                result = Encoding.ASCII.GetString(m_comObj.StartRead());
                try
                {
                    if(result == null)
                    {
                        result_f = 3;
                        record_message();
                        return -10000;
                    }
                    if (result.ToLower().Contains("failed"))
                    {
                        result = "getagl驱动失败";
                        record_message();
                        return -10000;
                    }
                                                            result_f = 1;
                    string sVal = result.Split('\n')[0].Split('=')[1].Trim();
                    record_message();
                    return Convert.ToInt32(sVal);
                }
                catch { }
            }
            result_f = 3;
            record_message();
            return -10000;
        }

        public RCUUnit get_info(string sn, int unit_index)
        {
            result = "";
            cmd = string.Format("getinfo {0},{1}\r\n", sn, unit_index);
            if (m_comObj.StartWrite(Encoding.ASCII.GetBytes(cmd)))
            {
                result = Encoding.ASCII.GetString(m_comObj.StartRead());
                try
                {

                                                                                                                                                                                                                                                                                                            
                                                                                                                                            
                    RCUUnit unit = new RCUUnit();
                    
                    string[] temp = result.Split('\n');
                    for(int i = 0;i < temp.Length; i++)
                    {
                        if (temp[i].ToLower().Contains("unitsum"))
                        {
                            unit.unit_sum = int.Parse(temp[i].Split(new char[] { '=', ':' })[1].Trim());
                        }
                        else if (temp[i].ToLower().Contains("unit"))
                        {
                                                        Regex reg = new Regex("(\\d+)");
                            var mch = reg.Matches(temp[i]);
                            if (mch.Count == 1)
                            {
                                unit.unit = Convert.ToInt32(mch[0].Value);
                            }
                        }
                        else if (temp[i].ToLower().Contains("modulenum"))
                        {
                            unit.module_num = temp[i].Split(new char[] { '=', ':' })[1].Trim();
                        }
                        else if (temp[i].ToLower().Contains("modulesn"))
                        {
                            unit.module_sn = temp[i].Split(new char[] { '=', ':' })[1].Trim();
                        }
                        else if (temp[i].ToLower().Contains("anle.min"))
                        {
                            unit.angle_min = float.Parse(temp[i].Split(new char[] { '=', ':' })[1].Trim());
                        }
                        else if (temp[i].ToLower().Contains("angle.min"))
                        {
                            unit.angle_min = float.Parse(temp[i].Split(new char[] { '=', ':' })[1].Trim());
                        }
                        else if (temp[i].ToLower().Contains("anle.max"))
                        {
                            unit.angle_max = float.Parse(temp[i].Split(new char[] { '=', ':' })[1].Trim());
                        }
                        else if (temp[i].ToLower().Contains("angle.max"))
                        {
                            unit.angle_max = float.Parse(temp[i].Split(new char[] { '=', ':' })[1].Trim());
                        }
                        else if (temp[i].ToLower().Contains("currentangle"))
                        {
                            unit.angle_current = float.Parse(temp[i].Split(new char[] { '=', ':' })[1].Trim());
                        }
                        else if (temp[i].ToLower().Contains("hardware version"))
                        {
                            unit.hardware_v = temp[i].Split(new char[] { '=', ':' })[1].Trim();
                        }
                        else if (temp[i].ToLower().Contains("firmware version"))
                        {
                            unit.firmvare_v = temp[i].Split(new char[] { '=', ':' })[1].Trim();
                        }
                        else if (temp[i].ToLower().Contains("aisg version"))
                        {
                            unit.aisg_v = temp[i].Split(new char[] { '=', ':' })[1].Trim();
                        }
                    }
                                                                                                                                                                                                                                                                                                                                                                                                                                    record_message();
                    return unit;
                }
                catch { }
            }
            record_message();
            return null;
        }

        public int calibration(string sn, int unit_index, int speed = 0)
        {
            result_f = 2;
            result = "";
            cmd = "CALI " + sn + "," + unit_index + "," + speed + "\r\n";
                        m_comObj.StartWrite(Encoding.ASCII.GetBytes(cmd), true);
            if (m_comObj.StartRead("calibrating", 4000) != null)
            {
                Byte[] b = m_comObj.StartRead("$->:", 1000 * 240);
                if (b == null)
                {
                    return -1;
                }

                                                                                result = Encoding.ASCII.GetString(b);
                if (result.ToLower().Contains("Calibration failed"))
                {
                    record_message();
                    return -1;
                }
                if (result.ToLower().Contains("succeed"))
                {
                    try
                    {
                        Regex rx = new Regex(@"(\d+)\.(\d+)|(\d+)");
                        MatchCollection ms = rx.Matches(result);
                        if (ms.Count > 0)
                        {
                            record_message();
                            return Convert.ToInt32(ms[0].Value);
                        }
                    }
                    catch { }
                }
            }
            result_f = 3;
            record_message();
            return -1;
        }

        public void reboot()
        {
            result = "";
            cmd = "reboot\r\n";
            m_comObj.StartWrite(Encoding.ASCII.GetBytes(cmd), true);

            record_message();
        }

        public bool get_help(string sn, out string hv, out string sv, out string build)
        {
            result = "";
            hv = sv = "";
            build = "";
            cmd = string.Format("help " + sn + "\r\n");
            Thread.Sleep(100);
            if (m_comObj.StartWrite(Encoding.ASCII.GetBytes(cmd), false, 2000))
            {
                result = Encoding.ASCII.GetString(m_comObj.StartRead());
                try
                {
                    string[] temp = result.Split('\n');
                    for (int i = 0; i < temp.Length; i++)
                    {
                        if (temp[i].ToLower().Contains("hardware version"))
                        {
                            hv = temp[i].Split(new char[] { '=', ':' })[1].Trim();
                        }
                        if (temp[i].ToLower().Contains("firmware version"))
                        {
                            sv = temp[i].Split(new char[] { '=', ':' })[1].Trim();
                        }
                        if (temp[i].ToLower().Contains("build date"))
                        {
                            build = temp[i].Split(new char[] { '=', ':' })[1].Trim();
                        }
                    }
                    record_message();
                    return true;
                }
                catch { }
            }

            record_message();
            return false;
        }
        #endregion

        #region 封装

        private RCUInfo getRCUinfo(string sn, int unit_index, ClsDataRcuConfig RCUConfig)
        {
            sn = sn.Replace("\r", "");
            RCUInfo info = new RCUInfo();
            
            info.SN = sn;
            
                                                                        
            Thread.Sleep(100);
                        RCUUnit unit = get_info(sn, unit_index);
            Thread.Sleep(100);

            string[] temp = sn.Split('-');
                        if (temp.Length == 3)
            {
                info.RCUIndex = sn.Split('-')[2];
            }
            else
            {
                for(int i = 0; i< RCUConfig.unit.Count; i++)
                {
                    string retport = "";
                    string truport = "";
                    truport = unit.module_sn.Substring(RCUConfig.unit[i].port_location - 1);
                    retport = unit.module_sn.Substring(RCUConfig.unit[i].port_location - 1).PadLeft(4, '-');
                    if(retport == RCUConfig.unit[i].port_name)
                    {
                        info.RCUIndex = truport;
                        break;
                    }

                    if(i == RCUConfig.unit.Count - 1)
                    {
                        System.Windows.Forms.MessageBox.Show("找不到对应端口符号的RCU配置文件");
                        return null;
                    }
                }
                
                            }

            unit.angle_current = get_agl(sn, unit.unit);
            info.angle = (int)unit.angle_current;
            info.unit = unit;

                                                                        
            return info;
        }

        public Dictionary<string, RCUInfo> getRCUInfoList(ClsDataRcuConfig RCUConfig = null)
        {
            try
            {
                                string[] lstRcuSN = get_list();
                if(lstRcuSN == null || lstRcuSN.Length == 0)
                {
                    System.Windows.Forms.MessageBox.Show("list错误，请重新连接RCU线缆");
                    return null;
                }

                                if(RCUConfig != null)
                {
                                        int tryCount = 30;
                    for (int k = 0; ; k++)
                    {
                        int sn_lenth = lstRcuSN[0].Length;
                        int index_num = lstRcuSN.Length;
                        if (index_num == RCUConfig.uid_count && sn_lenth == RCUConfig.uid_length)
                        {
                            break;
                        }
                        if (k == tryCount - 1)
                        {                               System.Windows.Forms.MessageBox.Show("无法获取UID");
                            return null;
                        }
                        lstRcuSN = get_list();
                    }
                }

                string sv, hv, build;
                if (!get_help(lstRcuSN[0], out hv, out sv, out build))
                {
                    return null;
                }

                                var dicRCUs = new Dictionary<string, RCUInfo>();
                for (int i = 0; i < lstRcuSN.Length; i++)
                {
                                        Thread.Sleep(100);
                    if (!set_debug_mode(lstRcuSN[i]))
                        return null;

                    RCUInfo info = getRCUinfo(lstRcuSN[i], 1, RCUConfig);
                    if(info.unit.hardware_v == "")
                        info.unit.hardware_v = hv;
                    if (info.unit.firmvare_v == "")
                        info.unit.firmvare_v = sv;
                    if (info.unit.build_date == "")
                        info.unit.build_date = build;

                    dicRCUs.Add(info.RCUIndex, info);
                                        for (int j = 2; j <= info.unit.unit_sum; j++)
                    {
                        RCUInfo info2 = getRCUinfo(lstRcuSN[i], j, RCUConfig);
                        info2.unit.hardware_v = hv;
                        info2.unit.firmvare_v = sv;
                        info2.unit.build_date = build;
                        dicRCUs.Add(info2.RCUIndex, info2);
                    }
                }
                                if (RCUConfig != null)
                {
                    for (int k = 0; k < RCUConfig.unit.Count; k++)
                    {
                        string index_now = RCUConfig.unit[k].port_name.Replace("-", string.Empty);
                        if (!dicRCUs.ContainsKey(index_now))
                        {
                            System.Windows.Forms.MessageBox.Show(index_now + "  端口名称不匹配");
                            return null;
                        }

                        if (dicRCUs[index_now].unit.unit_sum != RCUConfig.unit[k].unit_count)
                        {
                            System.Windows.Forms.MessageBox.Show(index_now + "  单元数量不匹配");
                            return null;
                        }

                        if(dicRCUs[index_now].unit.module_sn != null)
                        {
                            if (dicRCUs[index_now].unit.module_sn.Length != RCUConfig.unit[k].moduleSn_length)
                            {
                                System.Windows.Forms.MessageBox.Show(index_now + "  天线序列号长度不匹配");
                                return null;
                            }
                        }
                        else
                        {
                            if(dicRCUs[index_now].SN.Length != RCUConfig.unit[k].moduleSn_length)
                            {
                                System.Windows.Forms.MessageBox.Show(index_now + "  天线序列号长度不匹配");
                                return null;
                            }
                        }
                                                                                                                                            }
                }
                return dicRCUs;
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show("RCU 错误： " + ex.Message);
                return null;
            }

        }

        public bool setAngle(RCUInfo info, int need_agl, int need_speed)
        {
            string sn = info.SN;

            if (need_agl < info.unit.angle_min || need_agl > info.unit.angle_max)
            {
                System.Windows.Forms.MessageBox.Show("角度设置超出范围");
                return false;
            }

            Thread.Sleep(100);
            if (!set_debug_mode(sn))
            {
                return false;
            }

            Thread.Sleep(100);
            set_agl(sn, info.unit.unit, need_agl, need_speed);
            bool ret = RCUstate_check(sn, info.unit.unit);
            if (!ret)
            {
                return false;
            }
            info.unit.angle_current = need_agl;

            return true;
        }

        public bool revertAngle(RCUInfo info, int sorce_agl, int sorce_speed)
        {
            string sn = info.SN;
            float agl_move = 5;
            int check = 0;
                        float agl = sorce_agl;
                        if (agl >= (info.unit.angle_min + info.unit.angle_max) / 2.0)
                agl_move = -5;
            agl += agl_move;
            bool sed = set_agl(sn, info.unit.unit, (int)agl, 0);
            if (sed)
            {
                                agl -= agl_move;
                sed = set_agl(sn, info.unit.unit, (int)agl, 0);
            }
            if (sed)
                 check = get_agl(sn, info.unit.unit);
            if (check == agl)               {
                bool now = RCUstate_check(sn, info.unit.unit);
                if(now)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }

            else
            return false;
        }

        #endregion

        public void record_message()
        {
            string message = "";
            message += cmd;
            message += DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff") + "\r\n";
            if(result!="")
                message += result;
            else
                message += "无返回";
            message += DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff") + "\r\n";

            string sFilePath = System.Windows.Forms.Application.StartupPath + "\\LogMessage";
            if (!Directory.Exists(sFilePath))
            {
                Directory.CreateDirectory(sFilePath);
            }
            
            string sFileName = "ATE测试交互过程.txt";
            sFileName = sFilePath + "\\" + sFileName;             FileStream fs = new FileStream(sFileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
            StreamWriter sw = new StreamWriter(fs);
            sw.WriteLine(message);
            sw.Close();
            fs.Close();
        }

        public void output_message(ClsDataProduct product, clsUser usr, Dictionary<string, RCUInfo> infos, string type = "交调测试" )
        {
            ClsDataRcuConfig rcuConfig = null;
            if (product.rcuConfig == null)
            {
                rcuConfig = new ClsDataRcuConfig();
                rcuConfig.fileName = "无配置";
                rcuConfig.module_count = 1;
            }
              
            else
                rcuConfig = product.rcuConfig;

            string head = "生产日期,测试工号,测试类型,天线MO号,天线产品类型名称,天线产品代码,配置文件名,天线追溯号,模块数," +                             "硬件版本(Hardware Version),软件版本(Firmware Version),AISG版本(AISG Version),Build Date,设备序列号(SN)," +                              "UnitSum,单元号(UNIT),单元型号(MN),单元序列号(SN),RFnum,最终速度(SPD),设置角度的结果,当前角度";  
            StringBuilder op = new StringBuilder();
                        foreach (var data in infos)
            {
                op.Append(DateTime.Now.ToString("yyyy-MM-dd") + ",");                             op.Append(usr.userid + ",");                                                      op.Append(type + ",");                                                            op.Append(product.sMOID + ",");                                                   op.Append(product.sProcodeName + ",");                                            op.Append(product.sProcode + ",");                                                op.Append(rcuConfig.fileName + ",");                                              op.Append(product.sProductSN + ",");                                              op.Append(rcuConfig.module_count + ",");                          
                op.Append(data.Value.unit.hardware_v + ",");                                      op.Append(data.Value.unit.firmvare_v + ",");                                      op.Append(data.Value.unit.aisg_v + ",");                                          op.Append(data.Value.unit.build_date + ",");                                      op.Append(data.Value.SN + ",");                                   
                op.Append(data.Value.unit.unit_sum + ",");                                        op.Append(data.Value.unit.unit + ",");                                            op.Append(data.Value.unit.module_num + ",");                                      op.Append(data.Value.unit.module_sn + ",");                                       op.Append(data.Value.RCUIndex + ",");                                             op.Append("0" + ",");                                                             op.Append("true" + ",");                                                          op.Append(data.Value.unit.angle_current + "\r\n");                            }
            string sFilePath = System.Windows.Forms.Application.StartupPath + "\\TestResults";
            if (!Directory.Exists(sFilePath))
            {
                Directory.CreateDirectory(sFilePath);
            }
                        string sFileName = DateTime.Now.ToString(type) + ".csv";
            sFileName = sFilePath + "\\" + sFileName;             try
            {
                bool isExist = File.Exists(sFileName);
                FileStream fs = new FileStream(sFileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
                StreamWriter sw = new StreamWriter(fs, UnicodeEncoding.GetEncoding("GB2312"));
                if (!isExist)
                    sw.WriteLine(head);
                sw.Write(op.ToString());
                sw.Close();
                fs.Close();
            }
            catch(Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
                return;
            }

        }

        public bool RCUstate_check( string sn, int unit_index)
        {
            cmd = "";
            result = "";
            if(result_f == 2)
            {
                result = "驱动失败";
                record_message();
                System.Windows.Forms.MessageBox.Show("RCU驱动失败，请返修");
                return false;
            }
            if(result_f == 3)
            {
                int ret = get_agl(sn, unit_index);
                if(result_f == 1)
                {
                    result = "驱动超时";
                    record_message();
                    System.Windows.Forms.MessageBox.Show("驱动超时");
                    return false;
                }
                else if(result_f == 2)
                {
                    result = "驱动失败";
                    record_message();
                    System.Windows.Forms.MessageBox.Show("RCU驱动失败，请返修");
                    return false;
                }
                else if(result_f == 3)
                {
                    Thread.Sleep(3000);
                    ret = get_agl(sn, unit_index);
                    if (result_f == 1)
                    {
                        result = "驱动超时";
                        record_message();
                        System.Windows.Forms.MessageBox.Show("驱动超时");
                        return false;
                    }
                    else if (result_f == 2)
                    {
                        result = "驱动失败";
                        record_message();
                        System.Windows.Forms.MessageBox.Show("RCU驱动失败，请返修");
                        return false;
                    }
                    else if (result_f == 3)
                    {
                        result = "RCU处于离线状态";
                        record_message();
                        System.Windows.Forms.MessageBox.Show("RCU处于离线状态");
                        return false;
                    }
                }
            }
            result = "RCU驱动成功";
            record_message();
            return true;
        }
    }

    class RCUUnit
    {
        public string type { get; set; }
        public string hardware_v { get; set; }
        public string firmvare_v { get; set; }
        public string aisg_v { get; set; }
        public string build_date { get; set; }
        public int unit_sum { get; set; }
        public int unit { get; set; }
        public string module_num { get; set; }
        public string module_sn { get; set; }
        public float angle_min { get; set; }
        public float angle_max { get; set; }
        public float angle_current { get; set; }
        public RCUUnit()
        {
            unit = 1;
            unit_sum = 1;
            hardware_v = "";
            firmvare_v = "";
            aisg_v = "";
            build_date = "";
        }
    }

    class RCUInfo
    {
        public int angle { get; set; }
        public string SN { get; set; }
        public string RCUIndex { get; set; }
        public int revert_speed { get; set; }
        public RCUUnit unit { get; set; }
    }

}
